package payjsutil

import (
	"bytes"
	"sort"
	"strconv"
	"strings"
	"shop/utils/convertutil"
	"shop/utils/genutil"
	"shop/utils/httputil"
)

// payjs支付平台
const (
	// API 地址
	PayJSNativaUrl    = "https://payjs.cn/api/native"
	PayJSJsapiUrl     = "https://payjs.cn/api/jsapi"
	PayJSMicropayUrl  = "https://payjs.cn/api/micropay"
	PayJSCashierUrl   = "https://payjs.cn/api/cashier"
	PayJSCheckUrl     = "https://payjs.cn/api/check"
	PayJSCloseUrl     = "https://payjs.cn/api/close"
	PayJSReverseUrl   = "https://payjs.cn/api/reverse"
	PayJSRefundUrl    = "https://payjs.cn/api/refund"
	PayJSInfoUrl      = "https://payjs.cn/api/info"
	PayJSComplaintUrl = "https://payjs.cn/api/complaint"
	PayJSBankUrl      = "https://payjs.cn/api/bank"
	PayJSMwebUrl      = "https://payjs.cn/api/mweb"
)

type PayJsPayParams struct {
	PayJsMchId   string
	PayJsKey     string // 通信密钥
	PayJsOrderId string
	OutTradeNo   string // 自己系统的订单号
	TotalFee     int
	Body         string
	NotifyUrl    string
	CallBackUrl  string // 用户支付成功后，前端跳转地址, h5支付时才需要
}

// PayJsMp payJs支付小程序-跳转小程序方式支付
// 返回示例: {"body":"1","mchid":"1613001888","nonce":"rxNbUrwCqrOysyKA","notify_url":"https://xxl.today/naicha-api/pay/payJs/payNotify","out_trade_no":"1","sign":"7BCD6FCA9EDE296D68A89FDD6FB5A87C","total_fee":"1"}
func PayJsMp(params *PayJsPayParams) map[string]string {
	payData := map[string]string{
		"mchid":        params.PayJsMchId,
		"out_trade_no": params.OutTradeNo,
		"total_fee":    strconv.FormatInt(int64(params.TotalFee), 10),
		"nonce":        genutil.RandStr(16),
		"notify_url":   params.NotifyUrl,
		"body":         params.OutTradeNo,
	}
	PayJsSign(payData, params.PayJsKey)
	return payData
}

// PayJsPayQRCode payJs支付二维码-主动扫描支付
// 返回示例: {"return_code":1,"return_msg":"SUCCESS","payjs_order_id":"2021121421112700568080410","total_fee":"1","code_url":"weixin://wxpay/bizpayurl?pr=hJKBFT1zz","qrcode":"https://payjs.cn/qrcode/d2VpeGluOi8vd3hwYXkvYml6cGF5dXJsP3ByPWhKS0JGVDF6eg==","sign":"08F07AC2CEBF4793F0E81004B0996103"}
func PayJsPayQRCode(params *PayJsPayParams) map[string]interface{} {
	mapParams := map[string]string{
		"mchid":        params.PayJsMchId,
		"out_trade_no": params.OutTradeNo,
		"total_fee":    strconv.FormatInt(int64(params.TotalFee), 10),
		"body":         params.OutTradeNo,
		"notify_url":   params.NotifyUrl,
	}
	PayJsSign(mapParams, params.PayJsKey)

	res := map[string]interface{}{}
	convertutil.ParseJson(httputil.PostJson(PayJSNativaUrl, mapParams), &res)
	return res
}

// PayJSCashier h5收银台url方式，需要微信客户端支持
func PayJSCashier(params *PayJsPayParams) string {
	mapParams := map[string]string{
		"mchid":        params.PayJsMchId,
		"out_trade_no": params.OutTradeNo,
		"total_fee":    strconv.FormatInt(int64(params.TotalFee), 10),
		"body":         params.OutTradeNo,
		"notify_url":   params.NotifyUrl,
		"callback_url": params.CallBackUrl,
	}
	PayJsSign(mapParams, params.PayJsKey)

	return PayJSCashierUrl + "?" + httputil.ToQueryStr(mapParams)
}

// PayJsRefund 退款
func PayJsRefund(params *PayJsPayParams) map[string]string {
	mapParams := map[string]string{
		"mchid":          params.PayJsMchId,
		"payjs_order_id": params.PayJsOrderId,
	}
	PayJsSign(mapParams, params.PayJsKey)

	res := map[string]string{}
	convertutil.ParseJson(httputil.PostJson(PayJSRefundUrl, params), &res)
	return res
}

// PayJsSign 签名算法, md5加密->16进制->大写
func PayJsSign(params map[string]string, payJsKey string) string {
	keys := make([]string, 0, 8)
	for key := range params {
		if key != "" && key != "sign" && params[key] != "" {
			keys = append(keys, key)
		}
	}
	sort.Strings(keys)

	var buf bytes.Buffer
	for i := range keys {
		buf.WriteString(keys[i])
		buf.WriteByte('=')
		buf.WriteString(params[keys[i]])
		buf.WriteByte('&')
	}
	buf.WriteString("key=" + payJsKey)
	sign := strings.ToUpper(genutil.Md5Hex(buf.String()))
	params["sign"] = sign
	return sign
}
